#include "Token.h"


CString CScriptToken::ToString() const
{
    switch (Type)
    {
        case EScriptTokenType::Identifier:
        {
            auto Str=LiteralValue.GetValue().Get<CString>();
            return Str;
        }
        case EScriptTokenType::LiteralString:
        {
            auto Str=LiteralValue.GetValue().Get<CString>();
            return U'\"'+ Str + U'\"';
        }
        case EScriptTokenType::LiteralChar:
        {
            return CString(U'\'')+ LiteralValue.GetValue().Get<char32_t>() +U'\'';
        }
        case EScriptTokenType::LiteralBool:
        {
            return LiteralValue.GetValue().Get<bool>()?U"true":U"false";
        }
        case EScriptTokenType::LiteralNumber:
        {
            auto Value=LiteralValue.GetValue();

            if(Value.IsA<double>())
            {
                return CString(Value.Get<double>());
            }
            else if(Value.IsA<float>())
            {
                return CString(Value.Get<float>());
            }
            else if(Value.IsA<uint64_t>())
            {
                return CString(Value.Get<uint64_t>());
            }
            else
            {
                assert(false && "unimplemented literal number type");
            }
        }

        case EScriptTokenType::Null:
        {
            return U"null";
        }
        case EScriptTokenType::This:
        {
            return U"this";
        }
        case EScriptTokenType::Base:
        {
            return U"base";
        }
        case EScriptTokenType::New:
        {
            return U"new";
        }
        case EScriptTokenType::Return:
        {
            return U"return";
        }
        case EScriptTokenType::If:
        {
            return U"if";
        }
        case EScriptTokenType::Else:
        {
            return U"else";
        }
        case EScriptTokenType::For:
        {
            return U"for";
        }
        case EScriptTokenType::While:
        {
            return U"while";
        }
        case EScriptTokenType::Do:
        {
            return U"do";
        }
        case EScriptTokenType::Switch:
        {
            return U"switch";
        }
        case EScriptTokenType::Case:
        {
            return U"case";
        }
        case EScriptTokenType::Default:
        {
            return U"default";
        }
        case EScriptTokenType::Break:
        {
            return U"break";
        }
        case EScriptTokenType::Continue:
        {
            return U"continue";
        }
        case EScriptTokenType::Goto:
        {
            return U"goto";
        }
        case EScriptTokenType::In:
        {
            return U"in";
        }
        case EScriptTokenType::Is:
        {
            return U"is";
        }
        case EScriptTokenType::As:
        {
            return U"as";
        }
        case EScriptTokenType::Throw:
        {
            return U"throw";
        }
        case EScriptTokenType::Try:
        {
            return U"try";
        }
        case EScriptTokenType::Catch:
        {
            return U"catch";
        }
        case EScriptTokenType::Finally:
        {
            return U"finally";
        }
        case EScriptTokenType::Lock:
        {
            return U"lock";
        }
        case EScriptTokenType::Using:
        {
            return U"using";
        }
        case EScriptTokenType::Namespace:
        {
            return U"namespace";
        }
        case EScriptTokenType::Class:
        {
            return U"class";
        }
        case EScriptTokenType::Struct:
        {
            return U"struct";
        }
        case EScriptTokenType::Interface:
        {
            return U"interface";
        }
        case EScriptTokenType::Enum:
        {
            return U"enum";
        }
        case EScriptTokenType::Delegate:
        {
            return U"delegate";
        }
        case EScriptTokenType::Event:
        {
            return U"event";
        }
        case EScriptTokenType::Operator:
        {
            return U"operator";
        }
        case EScriptTokenType::Extern:
        {
            return U"extern";
        }
        case EScriptTokenType::Static:
        {
            return U"static";
        }
        case EScriptTokenType::Const:
        {
            return U"const";
        }
        case EScriptTokenType::Readonly:
        {
            return U"readonly";
        }
        case EScriptTokenType::Volatile:
        {
            return U"volatile";
        }
        case EScriptTokenType::Override:
        {
            return U"override";
        }
        case EScriptTokenType::Abstract:
        {
            return U"abstract";
        }
        case EScriptTokenType::Virtual:
        {
            return U"virtual";
        }
        case EScriptTokenType::Sealed:
        {
            return U"sealed";
        }
        case EScriptTokenType::Partial:
        {
            return U"partial";
        }
        case EScriptTokenType::Implicit:
        {
            return U"implicit";
        }
        case EScriptTokenType::Explicit:
        {
            return U"explicit";
        }
        case EScriptTokenType::Public:
        {
            return U"public";
        }
        case EScriptTokenType::Private:
        {
            return U"private";
        }
        case EScriptTokenType::Protected:
        {
            return U"protected";
        }
        case EScriptTokenType::Internal:
        {
            return U"internal";
        }
        case EScriptTokenType::Join:
        {
            return U"join";
        }
        case EScriptTokenType::Yield:
        {
            return U"yield";
        }
        case EScriptTokenType::Await:
        {
            return U"await";
        }
        case EScriptTokenType::Async:
        {
            return U"async";
        }
        case EScriptTokenType::From:
        {
            return U"from";
        }
        case EScriptTokenType::Select:
        {
            return U"select";
        }
        case EScriptTokenType::Where:
        {
            return U"where";
        }
        case EScriptTokenType::Group:
        {
            return U"group";
        }
        case EScriptTokenType::Into:
        {
            return U"into";
        }
        case EScriptTokenType::Let:
        {
            return U"let";
        }
        case EScriptTokenType::By:
        {
            return U"by";
        }
        case EScriptTokenType::Equal:
        {
            return U"==";
        }
        case EScriptTokenType::NotEqual:
        {
            return U"!=";
        }
        case EScriptTokenType::Less:
        {
            return U"<";
        }
        case EScriptTokenType::LessEqual:
        {
            return U"<=";
        }
        case EScriptTokenType::Greater:
        {
            return U">";
        }
        case EScriptTokenType::GreaterEqual:
        {
            return U">=";
        }
        case EScriptTokenType::AndAnd:
        {
            return U"&&";
        }
        case EScriptTokenType::OrOr:
        {
            return U"||";
        }
        case EScriptTokenType::PlusPlus:
        {
            return U"++";
        }
        case EScriptTokenType::MinusMinus:
        {
            return U"--";
        }
        case EScriptTokenType::LeftShift:
        {
            return U"<<";
        }
        case EScriptTokenType::RightShift:
        {
            return U">>";
        }
        case EScriptTokenType::PlusAssign:
        {
            return U"+=";
        }
        case EScriptTokenType::MinusAssign:
        {
            return U"-=";
        }
        case EScriptTokenType::MultiplyAssign:
        {
            return U"*=";
        }
        case EScriptTokenType::DivideAssign:
        {
            return U"/=";
        }
        case EScriptTokenType::ModAssign:
        {
            return U"%=";
        }
        case EScriptTokenType::AndAssign:
        {
            return U"&=";
        }
        case EScriptTokenType::OrAssign:
        {
            return U"|=";
        }
        case EScriptTokenType::XorAssign:
        {
            return U"^=";
        }
        case EScriptTokenType::LeftShiftAssign:
        {
            return U"<<=";
        }
        case EScriptTokenType::RightShiftAssign:
        {
            return U">>=";
        }
        case EScriptTokenType::Question:
        {
            return U"?";
        }
        case EScriptTokenType::Colon:
        {
            return U":";
        }
        case EScriptTokenType::Semicolon:
        {
            return U";";
        }
        case EScriptTokenType::Comma:
        {
            return U",";
        }
        case EScriptTokenType::Dot:
        {
            return U".";
        }
        case EScriptTokenType::Assign:
        {
            return U"=";
        }
        case EScriptTokenType::Not:
        {
            return U"!";
        }
        case EScriptTokenType::Tilde:
        {
            return U"~";
        }
        case EScriptTokenType::Plus:
        {
            return U"+";
        }
        case EScriptTokenType::Minus:
        {
            return U"-";
        }
        case EScriptTokenType::Multiply:
        {
            return U"*";
        }
        case EScriptTokenType::Divide:
        {
            return U"/";
        }
        case EScriptTokenType::Mod:
        {
            return U"%";
        }
        case EScriptTokenType::And:
        {
            return U"&";
        }
        case EScriptTokenType::Or:
        {
            return U"|";
        }
        case EScriptTokenType::Xor:
        {
            return U"^";
        }
        case EScriptTokenType::LeftParentheses:
        {
            return U"(";
        }
        case EScriptTokenType::RightParentheses:
        {
            return U")";
        }
        case EScriptTokenType::LeftBracket:
        {
            return U"[";
        }
        case EScriptTokenType::RightBracket:
        {
            return U"]";
        }
        case EScriptTokenType::LeftBrace:
        {
            return U"{";
        }
        case EScriptTokenType::RightBrace:
        {
            return U"}";
        }
        case EScriptTokenType::Var:
        {
            return U"var";
        }
        case EScriptTokenType::InnerType:
        {
            switch(InnerType.GetValue())
            {
                case EScriptInnerType::Bool:
                {
                    return U"bool";
                }
                case EScriptInnerType::Uint8:
                {
                    return U"byte";
                }
                case EScriptInnerType::Int8:
                {
                    return U"sbyte";
                }
                case EScriptInnerType::Int16:
                {
                    return U"short";
                }
                case EScriptInnerType::Uint16:
                {
                    return U"ushort";
                }
                case EScriptInnerType::Int32:
                {
                    return U"int32";
                }

                case EScriptInnerType::Uint32:
                {
                    return U"uint";
                }
                // case EScriptInnerType::Long:
                // {
                //     return U"long";
                // }
                // case EScriptInnerType::Ulong:
                // {
                //     return U"ulong";
                // }

                case EScriptInnerType::Int64:
                {
                    return U"int64";
                }

                case EScriptInnerType::Uint64:
                {
                    return U"uint64";
                }

                case EScriptInnerType::Float:
                {
                    return U"float";
                }

                case EScriptInnerType::Double:
                {
                    return U"double";
                }

                case EScriptInnerType::String:
                {
                    return U"string";
                }

                case EScriptInnerType::Object:
                {
                    return U"object";
                }

                case EScriptInnerType::Void:
                {
                    return U"void";
                }

                case EScriptInnerType::Char:
                {
                    return U"char";
                }

                // case EScriptInnerType::Nint:
                // {
                //     return U"nint";
                // }

                // case EScriptInnerType::Nuint:
                // {
                //     return U"nuint";
                // }

                default :
                {
                    assert(false&& "unimplemented inner type" );
                    return U"";
                }

            };

        }

    


        default:
        {
            assert(false&&"Unimplemented token type");
            return U"";
        }




    }
}

bool Token::IsAssignOperator(EScriptTokenType InType)
{
 
    return InType==EScriptTokenType::Assign
        || InType==EScriptTokenType::PlusAssign
        || InType==EScriptTokenType::MinusAssign
        || InType==EScriptTokenType::MultiplyAssign
        || InType==EScriptTokenType::DivideAssign
        || InType==EScriptTokenType::ModAssign
        || InType==EScriptTokenType::AndAssign
        || InType==EScriptTokenType::OrAssign
        || InType==EScriptTokenType::XorAssign
        || InType==EScriptTokenType::LeftShiftAssign
        || InType==EScriptTokenType::RightShiftAssign;
    
}
